#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>

#include "chip_demo_gpio_button.h"
#include "button_drv.h"


static int major;
static struct class *button_class;
struct button_chip_operations *button_chip_ops;


static int button_open (struct inode *node, struct file *filp)
{
	/* 
		打开设备时要获取其 次设备号
		通过次设备号初始化GPIO
	*/
	int minor = iminor(node);
	
	button_chip_ops->init(minor);

	return 0;
}


static ssize_t button_read (struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
	printk("button_read\n");
	return 0;
}


static ssize_t button_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
	/* 根据次设备号和 status 控制 button */
	struct inode *inode = file_inode(filp);
	int minor = iminor(inode);
	char status, err;
	
	err = copy_from_user(&status, buf, 1);
	button_chip_ops->ctl(minor, status);
	return 0;
}


static int button_release (struct inode *node , struct file *filp)
{
	int minor = iminor(node);
	printk("/dev/button%d close\n", minor);

	return 0;
}

/* 异步通知 */
static int button_fasync (int fd, struct file *filp, int on)
{
	printk(KERN_EMERG "key_fasync enter!\n");
	return 1;
}

static struct file_operations button_ops = {
	.owner		= THIS_MODULE,
	.open 		= button_open,
	.read 		= button_read,
	.write 		= button_write,
	.fasync 	= button_fasync,
	.release    = button_release,
};


/*为硬件操作层提供注册设备节点函数*/
void button_device_create(int minor, char *name)
{
	device_create(button_class, NULL, MKDEV(major, minor), NULL, "%s", name);   // /dev/name
}

/*为硬件操作层提供销毁设备节点函数*/
void button_device_destroy(int minor)
{
	device_destroy(button_class, MKDEV(major, minor));
}

/*获取硬件操作层的 button_chip_operations 结构体*/
void get_button_resources(struct button_chip_operations *ops)
{
	button_chip_ops = ops;
}	

EXPORT_SYMBOL(button_device_create);
EXPORT_SYMBOL(button_device_destroy);
EXPORT_SYMBOL(get_button_resources);


/*button驱动入口函数：insmod时会被调用*/
static int button_drv_init(void)
{
	/* 1.注册设备 */
	major = register_chrdev(0, "button_board_drv", &button_ops);

	/* 2.自动创建设备节点 */
	/* 2.1 在内核中创建设备 */
	button_class = class_create(THIS_MODULE, "button_class");

	
	/* 2.2 创建设备节点 */
	/*
		获取button_chip_ops结构体：
		定义了button个数、button初始化函数、button控制函数
	*/
//	button_chip_ops = get_button_chip_ops();
	/* 指定次设备号创建/dev设备 */
//	device_create(button_class, NULL, MKDEV(major, 0), NULL, "button");   // /dev/button

	printk("button driver insmod success\n");
	return 0;
}


/*button驱动出口函数：rmmod时会被调用*/
static void button_drv_exit(void)
{
	/* 1.销毁设备节点 */
//	device_destroy(button_class, MKDEV(major, 0));

	/* 2.销毁设备类 */
	class_destroy(button_class);

	/* 3.卸载设备 */
	unregister_chrdev(major, "button_board_drv");

	printk("button driver exit\n");
}

module_init(button_drv_init);
module_exit(button_drv_exit);
MODULE_LICENSE("GPL");





